package com.tanhua.manager.service;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tanhua.manager.domain.Admin;
import com.tanhua.manager.exceptions.TanhuaErrorEnums;
import com.tanhua.manager.exceptions.TanhuaException;
import com.tanhua.manager.interceptors.AdminHolder;
import com.tanhua.manager.mapper.AdminMapper;
import com.tanhua.manager.utils.JwtUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class AdminService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private AdminMapper adminMapper;


//    存储token的前缀
    private static final String CACHE_KEY_TOKEN_PREFIX="MANAGE_TOKEN_";
//  存储验证码的前缀
    private static final String CACHE_KEY_CAP_PREFIX = "MANAGE_CAP_";


    //根据登录token，获取用户对象
    public Admin findAdminByToken(String token) {
        String adminStr = redisTemplate.boundValueOps(CACHE_KEY_TOKEN_PREFIX+token).get();
        if(adminStr == null) {
            return null;
        }
        redisTemplate.boundValueOps(CACHE_KEY_TOKEN_PREFIX+token).set(adminStr,2, TimeUnit.HOURS);//续期
        return JSON.parseObject(adminStr,Admin.class);
    }


    /**
     * 从redis中删除token缓存
     */
    public void removeToken(String token){
        String redisTokenKey = CACHE_KEY_TOKEN_PREFIX + token;
        this.redisTemplate.delete(redisTokenKey);
    }

//    获取验证码图片
    public ResponseEntity verification(String uuid, HttpServletResponse response) throws Exception {
//        CAPTCHA
        LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(300, 100);//长度和高度
//        lineCaptcha 验证码对象
//        把验证码对象中的值存储到redis中  可以设置一个失效时间
        String code = lineCaptcha.getCode();
        redisTemplate.boundValueOps(CACHE_KEY_CAP_PREFIX+uuid).set(code,5,TimeUnit.MINUTES);
//        向浏览器返回验证码图片
        lineCaptcha.write(response.getOutputStream());
        return ResponseEntity.ok(null);
    }

    public ResponseEntity login(String username, String password, String verificationCode, String uuid) {
//        1、判断用户名和密码是否为空
        if(StringUtils.isBlank(username)||StringUtils.isBlank(password)){
            throw new TanhuaException(TanhuaErrorEnums.USERNAME_PASSWORD_ISNULL);
        }
//        2、是否能从redis中获取验证码
        String code = redisTemplate.boundValueOps(CACHE_KEY_CAP_PREFIX + uuid).get();
        if(StringUtils.isBlank(code)){
            throw new TanhuaException(TanhuaErrorEnums.CAPTCHA_ISNULL);
        }
//        3、判断验证码是否正确  equalsIgnoreCase:忽略大小写
        if(!StringUtils.equalsIgnoreCase(verificationCode,code)){
            throw new TanhuaException(TanhuaErrorEnums.CAPTCHA_FAIL);
        }
//        4、只根据用户名登录
        QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Admin::getUsername,username);
        Admin admin = adminMapper.selectOne(queryWrapper);

//       如果查不到 意味着用户错误
        if(admin==null){
            throw new TanhuaException(TanhuaErrorEnums.USERNAME_ERROR);
        }
//                如果有用户，继续判断密码
//   先把页面传过来的密码加密 然后再和表中的密码比较
        password = DigestUtils.md5Hex(password);
        String password_db = admin.getPassword();
        if(!StringUtils.equals(password,password_db)){
//            如果密码不相等密码错误
            throw new TanhuaException(TanhuaErrorEnums.PASSWORD_ERROR);
        }
//     如果密码相等登录成功过 生成token

        String token = JwtUtils.createToken(username, admin.getId(), "tanhua-manager");
//        需要把token存储到redis中

        String adminJson = JSON.toJSONString(admin);
        redisTemplate.boundValueOps(CACHE_KEY_TOKEN_PREFIX+token).set(adminJson,24,TimeUnit.HOURS);

//        可以把redis中的验证码删除
        redisTemplate.delete(CACHE_KEY_CAP_PREFIX + uuid);

        Map map = new HashMap();
        map.put("token",token);

        return ResponseEntity.ok(map);


    }


    //    存储token到redis中
    public void saveTokenToRedis(Admin admin,String token) {
        String adminJson = JSON.toJSONString(admin);
        redisTemplate.boundValueOps(CACHE_KEY_TOKEN_PREFIX+token).set(adminJson,24,TimeUnit.HOURS);
    }

//    清空redis中的token
    public ResponseEntity logout() {
        Admin admin = AdminHolder.getAdmin();
        String token = admin.getToken();
        redisTemplate.delete(CACHE_KEY_TOKEN_PREFIX+token);
        return ResponseEntity.ok(null);
    }
}